package com.cn.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.StringTokenizer;

import com.cn.xc.utils.StringUtil;

/**
 * FUN: mapper 基类
 *
 * @author sushy
 * @date 2016-3-23 
 */
public abstract class BaseMapper <T> implements IMapper<T> {

	private boolean isBranchTable;// 是否分表
	private String tableName;// 表名
	private String tableColumnNames;// 字段名
	private String[] columnNames;// 字段名
	private String[] keyColumnNames;// 主键字段
	private String[] propertiesNames;// 生成的属性字段信息
	private String insertSql;// 生成的insert语句
	private String updateSql;// 生成的update语句
	private String keySql;// 生成的主键条件语句
	private String deleteSql;// 生成的delete语句
	private String selectSql;// 生成的查询语句
	private boolean isHaveKey;// 是否有主键

	public BaseMapper(String tableName, String columnNames,
			String keyColumnNames, boolean isBranchTable) {
		this.tableColumnNames = columnNames;
		this.isBranchTable = isBranchTable;
		if (this.isBranchTable) {
			// 去掉0~9，加上后缀$tableSuffix$
			int endIndex = tableName.length() - 1;
			char n = tableName.charAt(endIndex);
			if (n >= '0' && n <= '9') {
				tableName = tableName.substring(0, endIndex);
			}
			this.tableName = new StringBuilder(tableName).append(
					"$tableSuffix$").toString();// 加上表后缀
		} else {
			this.tableName = tableName;
		}

		// 字段信息
		int i = 0;
		StringTokenizer token = new StringTokenizer(columnNames, ",");
		this.columnNames = new String[token.countTokens()];
		while (token.hasMoreTokens()) {
			this.columnNames[i] = token.nextToken();
			++i;
		}

		// 主键字段信息
		if (StringUtil.isNotEmpty(keyColumnNames)) {
			i = 0;
			token = new StringTokenizer(keyColumnNames, ",");
			this.keyColumnNames = new String[token.countTokens()];
			while (token.hasMoreTokens()) {
				this.keyColumnNames[i] = token.nextToken();
				++i;
			}
		}
		token = null;

		// 初始化sql
		init();
	}

	/**
	 * 初始化sql语句
	 */
	private void init() {
		propertiesNames = genPropertiesNames(columnNames);
		selectSql = genSelectSql(tableName, columnNames, propertiesNames);
		insertSql = genInsertSql(tableName, columnNames, propertiesNames);
		updateSql = genUpdateSql(tableName, columnNames, propertiesNames);
		deleteSql = genDeleteSql(tableName);
		isHaveKey = (keyColumnNames != null && keyColumnNames.length > 0);
		if (isHaveKey) {
			keySql = genKeySql(keyColumnNames);
		} else {
			keySql = "where rownum<1 ";
		}
	}

	public boolean isHaveKey() {
		return isHaveKey;
	}

	public String getTableName() {
		return tableName;
	}

	public String getTableColumnNames() {
		return tableColumnNames;
	}

	public String[] getColumnNames() {
		return columnNames;
	}

	public String[] getPropertiesNames() {
		return propertiesNames;
	}

	/**
	 * 获取新增sql
	 * 
	 * @return
	 */
	public String getInsertSql() {
		return insertSql;
	}

	/**
	 * 获取更新sql
	 * 
	 * @return
	 */
	public String getUpdateSql() {
		return updateSql;
	}

	/**
	 * 获取主键条件sql
	 * 
	 * @return
	 */
	public String getKeySql() {
		return keySql;
	}

	/**
	 * 获取删除sql
	 * 
	 * @return
	 */
	public String getDeleteSql() {
		return deleteSql;
	}

	/**
	 * 获取查询sql
	 * 
	 * @return
	 */
	public String getSelectSql() {
		return selectSql;
	}

	/**
	 * RowMapper
	 */
	public abstract T mapRow(ResultSet resultset, int i) throws SQLException;

	/**
	 * 读取resultSet到bean
	 * 
	 * @param resultset
	 * @param objBean
	 * @return
	 */
	public abstract void loadNext(RowSet resultset, T objBean);

	/**
	 * 根据字段名获取属性名
	 * 
	 * @param columnName
	 * @return
	 */
	public static String genPropertiesName(String columnName) {
		StringBuilder sb = new StringBuilder();
		String fieldName = columnName.toLowerCase();
		StringTokenizer token = new StringTokenizer(fieldName, "_");
		while (token.hasMoreTokens()) {
			sb.append(first2Upper(token.nextToken()));
		}
		return first2Lower(sb.toString());
	}

	/**
	 * 根据字段名获取属性名
	 * 
	 * @param columnNames
	 * @return
	 */
	protected static String[] genPropertiesNames(String[] columnNames) {
		String[] propertiesNames = new String[columnNames.length];
		for (int i = 0; i < propertiesNames.length; ++i) {
			propertiesNames[i] = genPropertiesName(columnNames[i]);
		}
		return propertiesNames;
	}

	/**
	 * 第一个字母变大写
	 * 
	 * @param str
	 * @return
	 */
	public static String first2Upper(String str) {
		return Character.toUpperCase(str.charAt(0)) + str.substring(1);
	}

	/**
	 * 第一个字母变小写
	 * 
	 * @param str
	 * @return
	 */
	public static String first2Lower(String str) {
		return Character.toLowerCase(str.charAt(0)) + str.substring(1);
	}

	/**
	 * 生成insert语句
	 * 
	 * @param tableName
	 * @param columnNames
	 * @param propertiesNames
	 * @return
	 */
	protected static String genInsertSql(String tableName,
			String[] columnNames, String[] propertiesNames) {
		StringBuilder sql = new StringBuilder();
		sql.append("insert into ").append(tableName.toLowerCase()).append(" (");
		for (int i = 0; i < columnNames.length; ++i) {
			if (i > 0) {
				sql.append(",");
			}
			sql.append(columnNames[i]);
		}
		sql.append(") values(");
		for (int i = 0; i < propertiesNames.length; ++i) {
			if (i > 0) {
				sql.append(",");
			}
			sql.append(":").append(propertiesNames[i]);
		}
		sql.append(")");
		return sql.toString();
	}

	/**
	 * 生成update语句
	 * 
	 * @param tableName
	 * @param columnNames
	 * @param propertiesNames
	 * @return
	 */
	protected static String genUpdateSql(String tableName,
			String[] columnNames, String[] propertiesNames) {
		StringBuilder sql = new StringBuilder();
		sql.append("update ").append(tableName).append(" set ");
		for (int i = 0; i < columnNames.length; ++i) {
			if (i > 0) {
				sql.append(",");
			}
			sql.append(columnNames[i]).append("=:").append(propertiesNames[i]);
		}
		sql.append(" ");
		return sql.toString();
	}

	/**
	 * 生成主键条件语句
	 * 
	 * @param keyColumnNames
	 * @return
	 */
	protected static String genKeySql(String[] keyColumnNames) {
		StringBuilder sql = new StringBuilder();
		for (int i = 0; i < keyColumnNames.length; ++i) {
			if (i > 0) {
				sql.append(" and ");
			} else {
				sql.append(" where ");
			}
			sql.append(keyColumnNames[i]).append("=:")
					.append(genPropertiesName(keyColumnNames[i])).append(" ");
		}
		return sql.toString();
	}

	/**
	 * 生成删除语句
	 * 
	 * @param tableName
	 * @param sql
	 * @return
	 */
	protected static String genDeleteSql(String tableName) {
		return new StringBuilder("delete from ").append(tableName).append(" ")
				.toString();
	}

	/**
	 * 生成查询语句
	 * 
	 * @param tableName
	 * @param columnNames
	 * @param propertiesNames
	 * @return
	 */
	protected static String genSelectSql(String tableName,
			String[] columnNames, String[] propertiesNames) {
		StringBuilder sql = new StringBuilder();
		sql.append("select ");
		for (int i = 0; i < columnNames.length; ++i) {
			if (i > 0) {
				sql.append(",");
			}
			sql.append(columnNames[i]);
		}
		sql.append(" from ").append(tableName);
		return sql.toString();
	}

	public boolean isBranchTable() {
		return isBranchTable;
	}

	public String getTableSuffix(long id) {
		if (isBranchTable) {
			return String.valueOf(id % 10);
		}
		return "";
	}


}
